using System;
using Tycho.Runtime;

namespace Tycho.PerformanceTests {
    class IntegerOperations {
        [BenchMark, Ignore]
        static void InvokeMethod () {
            AnyObject i = 0;
            AnyObject limit = 1000000;
            AnyObject increment = 1;
            while ((bool) i.InvokeMethod (i, Symbols.RuntimeLessThan, limit)) {
                i = i.InvokeMethod (i, Symbols.RuntimePlus, increment);
            }
        }

        [BenchMark, Ignore]
        static void Script () {
            TopLevel topLevel = new TopLevel ();
            topLevel.Evaluate (@"
i := 0
while i < 1000000
    i := i + 1");
        }

        [BenchMark, Ignore]
        static void Fast () {
            FastAnyObject i = new IntegerAnyObject (0);
            IntegerAnyObject limit = new IntegerAnyObject (1000000);
            IntegerAnyObject increment = new IntegerAnyObject (1);
            while ((bool) i.LessThan (limit)) {
                i = i.Plus (increment);
            }
        }

        [BenchMark, Ignore]
        static void VirtualMethod () {
            AnyObject i = 0;
            AnyObject limit = 1000000;
            AnyObject increment = 1;
            while ((bool) i.LessThan (limit)) {
                i = i.Plus (increment);
            }
        }
    }

    abstract class FastAnyObject {
        public abstract FastAnyObject LessThan (FastAnyObject arg);
        public abstract FastAnyObject Plus (FastAnyObject arg);

        public static explicit operator bool (FastAnyObject a) {
            return a.BoolValue;
        }

        public abstract bool BoolValue { get; }
    }

    class IntegerAnyObject : FastAnyObject {
        private int Value;

        public IntegerAnyObject (int value) {
            Value = value;
        }

        public override FastAnyObject LessThan (FastAnyObject arg) {
            if (arg is IntegerAnyObject) {
                return new BooleanAnyObject (Value < (arg as IntegerAnyObject).Value);
            } else {
                throw new ApplicationException ("no matching method");
            }
        }

        public override FastAnyObject Plus (FastAnyObject arg) {
            if (arg is IntegerAnyObject) {
                return new IntegerAnyObject (Value + (arg as IntegerAnyObject).Value);
            } else {
                throw new ApplicationException ("no matching method");
            }
        }

        public override bool BoolValue {
            get { throw new System.NotImplementedException (); }
        }
    }

    class BooleanAnyObject : FastAnyObject {
        private bool Value;

        public BooleanAnyObject (bool value) {
            Value = value;
        }

        public override FastAnyObject LessThan (FastAnyObject arg) {
            throw new System.NotImplementedException ();
        }

        public override FastAnyObject Plus (FastAnyObject arg) {
            throw new System.NotImplementedException ();
        }

        public override bool BoolValue {
            get { return Value; }
        }
    }
}